home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
001-025
/
scopedisk18
/
muncho
/
audio.c
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
10KB
|
419 lines
#include <lattice/stdio.h>
#include <exec/types.h>
#include <devices/audio.h>
#include <devices/timer.h>
#define TICKS_PER_SEC (3579545.0)
#define PRIORITY (100)
#define SOUND_PRIORITY (50)
#define MAXBUF (131000)
extern struct MsgPort *CreatePort();
extern struct IOAudio *GetMsg();
int timOpened;
int finOpened;
UBYTE allocMap[] = {1,2,4,8};
int inUse[] = {0,0,0,0};
struct MsgPort *port5_ = NULL;
struct MsgPort *port6_ = NULL;
struct MsgPort *port7_ = NULL;
struct MsgPort *port8_ = NULL;
struct MsgPort *port9_ = NULL;
struct MsgPort *port10_ = NULL;
struct MsgPort *port11_ = NULL;
struct IOAudio sIO1;
struct IOAudio sIO2;
struct IOAudio sIO3;
struct IOAudio sIO4;
struct IOAudio finishIO;
struct IOAudio ctlIO;
struct IOAudio flushIO;
struct IOAudio *sIOarray_[4];
struct timerequest timReq;
long timMsg;
struct MsgPort *timPort_ = NULL;
int nextTry;
static int doneInit = 0;
^L
/*
---------------------------------------------------------------------------
audio_init
---------------------------------------------------------------------------
Initializes the audio device.
Receives:
<nothing>
Returns:
int status -completion status
0 ==> OK
===========================================================================
*/
audio_init()
{
doneInit = 1;
/*
Open the audio device:
======================*/
if(!(port5_=CreatePort("s5",0))){
return(2);
}
if(!(port6_=CreatePort("s6",0))){
return(2);
}
if(!(port7_=CreatePort("s7",0))){
return(2);
}
if(!(port8_=CreatePort("s8",0))){
return(2);
}
if(!(port9_=CreatePort("ctrl2",0))){
return(3);
}
if(!(port10_ = CreatePort("ctrl3",0))){
return(3);
}
if(!(port11_ = CreatePort("ctrl4",0))){
return(3);
}
if(OpenDevice(AUDIONAME,0,&finishIO,0)){
finOpened = 0;
return(4);
}
finOpened = 1;
/*
Initialize the audio request blocks:
====================================*/
sIO1 = finishIO;
sIO2 = finishIO;
sIO3 = finishIO;
sIO4 = finishIO;
flushIO = finishIO;
ctlIO = finishIO;
sIO1.ioa_Request.io_Message.mn_ReplyPort = port5_;
sIO2.ioa_Request.io_Message.mn_ReplyPort = port6_;
sIO3.ioa_Request.io_Message.mn_ReplyPort = port7_;
sIO4.ioa_Request.io_Message.mn_ReplyPort = port8_;
finishIO.ioa_Request.io_Message.mn_ReplyPort = port9_;
flushIO.ioa_Request.io_Message.mn_ReplyPort = port10_;
ctlIO.ioa_Request.io_Message.mn_ReplyPort = port11_;
finishIO.ioa_Request.io_Flags = IOF_QUICK;
finishIO.ioa_Request.io_Command = ADCMD_FINISH;
finishIO.ioa_Data = NULL;
finishIO.ioa_Length = 0;
flushIO.ioa_Request.io_Flags = IOF_QUICK;
flushIO.ioa_Request.io_Command = CMD_FLUSH;
flushIO.ioa_Data = NULL;
flushIO.ioa_Length = 0;
flushIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
sIO1.ioa_Request.io_Command = CMD_WRITE;
sIO1.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
sIO2.ioa_Request.io_Command = CMD_WRITE;
sIO2.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
sIO3.ioa_Request.io_Command = CMD_WRITE;
sIO3.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
sIO4.ioa_Request.io_Command = CMD_WRITE;
sIO4.ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK|ADIOF_SYNCCYCLE;
sIOarray_[0] = &(sIO1);
sIOarray_[1] = &(sIO2);
sIOarray_[2] = &(sIO3);
sIOarray_[3] = &(sIO4);
/*
Open a timer:
=============*/
if(!(timPort_=CreatePort(0,0))){
return(10);
}
timReq.tr_node.io_Message.mn_ReplyPort = timPort_;
if(OpenDevice(TIMERNAME,UNIT_VBLANK,&timReq,0)){
timOpened = 0;
return(11);
}
timOpened = 1;
timReq.tr_node.io_Message.mn_ReplyPort = timPort_;
timReq.tr_node.io_Command = TR_ADDREQUEST;
timReq.tr_node.io_Flags = 0;
timReq.tr_node.io_Error = 0;
timMsg = 1L << timPort_->mp_SigBit;
nextTry = 0;
return(0);
}
^L
/*
---------------------------------------------------------------------------
audio_sound
---------------------------------------------------------------------------
Simulates the sound of a picked string.
Receives:
BYTE *s_ -pointer to the data for the sound
int sLen -length of sound data in bytes
int volume -volume (0 to 64)
Returns:
<nothing>
===========================================================================
*/
audio_sound(s_,sLen,period,volume)
BYTE *s_;
ULONG sLen;
int period;
int volume;
{
struct IOAudio *mySound_;
int ch;
int u;
int k;
/*
Check if there's any IO requests that have finished:
====================================================*/
ch = GetChannel(&u,&k);
/*
Setup the number of repeats:
============================*/
mySound_ = sIOarray_[ch];
/*
Setup the sound message:
========================*/
mySound_->ioa_Data = s_;
mySound_->ioa_Period = period;
mySound_->ioa_Length = sLen;
mySound_->ioa_Cycles = 1;
mySound_->ioa_Volume = volume;
mySound_->ioa_AllocKey = k;
mySound_->ioa_Request.io_Flags = ADIOF_PERVOL;
mySound_->ioa_Request.io_Unit = u;
mySound_->ioa_Request.io_Message.mn_Node.ln_Pri = SOUND_PRIORITY;
/*
Play the sound:
===============*/
BeginIO(mySound_);
return(0);
}
^L
^L
/*
---------------------------------------------------------------------------
audio_close
---------------------------------------------------------------------------
Closes the audio device and de-allocates all associated memory.
Receives:
<nothing>
Returns:
<nothing>
===========================================================================
*/
audio_close()
{
int i;
struct IOAudio *msg_;
if(doneInit){
for(i=0; i<4; i++){
flushIO.ioa_Request.io_Flags = IOF_QUICK;
flushIO.ioa_Request.io_Command = ADCMD_FINISH;
flushIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
flushIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
DoIO(&flushIO);
finishIO.ioa_Request.io_Flags = IOF_QUICK;
finishIO.ioa_Request.io_Command = ADCMD_FINISH;
finishIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
finishIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
DoIO(&finishIO);
ctlIO.ioa_Request.io_Command = ADCMD_FREE;
ctlIO.ioa_Request.io_Flags = IOF_QUICK;
ctlIO.ioa_Data = NULL;
ctlIO.ioa_Length = 0;
ctlIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
ctlIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
DoIO(&ctlIO);
while(msg_=GetMsg(sIOarray_[i]->ioa_Request.io_Message.mn_ReplyPort)){
}
}
}
if(finOpened){
CloseDevice(&finishIO);
}
if(timOpened){
CloseDevice(&timReq);
}
if(timPort_){
DeletePort(timPort_);
}
if(port5_){
DeletePort(port5_);
}
if(port6_){
DeletePort(port6_);
}
if(port7_){
DeletePort(port7_);
}
if(port8_){
DeletePort(port8_);
}
if(port9_){
DeletePort(port9_);
}
if(port10_){
DeletePort(port10_);
}
if(port11_){
DeletePort(port11_);
}
return(0);
}
^L
/*
---------------------------------------------------------------------------
audio_delay
---------------------------------------------------------------------------
Delays for a given amount of time. (Used for the time between
notes.)
Receives:
int hsecs -length of time to delay in hundredths of a sec
Returns:
<nothing>
===========================================================================
*/
audio_delay(hsecs)
int hsecs;
{
timReq.tr_time.tv_secs = (int)(hsecs/100);
timReq.tr_time.tv_micro = (int)(hsecs%100) * 10000;
DoIO(&timReq);
return(0);
}
^L
/*
---------------------------------------------------------------------------
EmptyPorts
---------------------------------------------------------------------------
Used internaly by th audio routines. Waits for each pending
audio request and frees the request when it finishes.
Receives:
<nothing>
Returns:
<nothing>
===========================================================================
*/
EmptyPorts()
{
struct IOAudio *GetMsg();
struct IOAudio *msg_;
int i;
for(i=0; i<4; i++){
if(inUse[i]){
while(msg_=GetMsg(sIOarray_[i]->ioa_Request.io_Message.mn_ReplyPort)){
inUse[i] = 0;
}
if(!inUse[i]){
ctlIO.ioa_Request.io_Command = ADCMD_FREE;
ctlIO.ioa_Request.io_Flags = IOF_QUICK;
ctlIO.ioa_Data = NULL;
ctlIO.ioa_Length = 0;
ctlIO.ioa_AllocKey = sIOarray_[i]->ioa_AllocKey;
ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
ctlIO.ioa_Request.io_Unit = sIOarray_[i]->ioa_Request.io_Unit;
DoIO(&ctlIO);
}
}
}
return(0);
}
^L
/*
---------------------------------------------------------------------------
GetChannel
---------------------------------------------------------------------------
Finds a free channel, or if they're all busy, cancels the
oldest one and frees it.
Receives:
int *u_ -pointer to space for the unit
int *k_ -pointer to space for the key
Returns:
int *u_ -the free channel's unit
int *k_ -the free channel's key
===========================================================================
*/
GetChannel(u_,k_)
int *u_;
int *k_;
{
int ch;
while(1){
EmptyPorts();
ctlIO.ioa_Request.io_Command = ADCMD_ALLOCATE;
ctlIO.ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK;
ctlIO.ioa_Data = allocMap;
ctlIO.ioa_AllocKey = 0;
ctlIO.ioa_Request.io_Unit = NULL;
ctlIO.ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY;
ctlIO.ioa_Length = sizeof(allocMap);
BeginIO(&ctlIO);
if(!WaitIO(&ctlIO)){
*u_ = (int)(ctlIO.ioa_Request.io_Unit);
*k_ = (int)(ctlIO.ioa_AllocKey);
break;
}
}
while(1){
for(ch=0; ch<4; ch++){
if(!inUse[ch]){
inUse[ch] = 1;
nextTry = (ch+1)%4;
return(ch);
}
}
EmptyPorts();
}
}
^L
/*
---------------------------------------------------------------------------
audio_free
---------------------------------------------------------------------------
Frees all of the channels.
Receives:
<nothing>
Returns:
<nothing>
===========================================================================
*/
audio_free()
{
while(inUse[0]+inUse[1]+inUse[2]+inUse[3]){
EmptyPorts();
}
return(0);
}